package cn.darkhorse.device.iot.sqlbuilder;

import cn.darkhorse.device.iot.ISqlBuilder;
import cn.darkhorse.device.iot.constant.IotConstant;
import cn.darkhorse.device.pojo.IotPointTable;
import cn.darkhorse.device.service.IotPointTableService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 星原网关，Sql构建器
 */
@Component("defaultSqlBuilder")
public class DefaultSqlBuilder implements ISqlBuilder {
    private static final Logger log = LoggerFactory.getLogger(DefaultSqlBuilder.class);
    @Resource
    private IotPointTableService iotPointTableService;


    /**
     * 获取设备点位和历史表字段之间的对应关系
     * @param gatewayDeviceId
     * @return Map<String, String> key=pointId, value=fieldName
     */
    private Map<String, String> getPointFieldLookup(String gatewayDeviceId) {
        // Step.1 获取设备点表
        List<IotPointTable> pointTables = iotPointTableService.list(new LambdaQueryWrapper<IotPointTable>()
                .eq(IotPointTable::getGatewayDeviceId, gatewayDeviceId));

        // 转换为map
        return pointTables.stream().collect(Collectors.toMap(IotPointTable::getPointId, IotPointTable::getFieldName));
    }

    @Override
    public String build(Map<String, Object> params, String gatewayDeviceId, LocalDateTime createdAt) {
        Map<String, String> pointFieldLookup = getPointFieldLookup(gatewayDeviceId);

        String historyTableName = IotConstant.HISTORY_TABLE_NAME_PRE + gatewayDeviceId;

        String insert = String.format("insert into %s",historyTableName);
        String field = " (%s) ";
        String values = " values(%s) ";

        StringBuilder fieldSb = new StringBuilder();
        StringBuilder valuesSb = new StringBuilder();

        Iterator<Map.Entry<String, Object>> iterator = params.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, Object> entry = iterator.next();
            String fieldName = pointFieldLookup.get(entry.getKey());
            if (StringUtils.isEmpty(fieldName)) {
                continue;
            }
            fieldSb.append(fieldName).append(",");
            valuesSb.append("'").append(entry.getValue()).append("'").append(",");
        }

        fieldSb.append(IotConstant.FIELD_NAME_CREATED_AT).append(",");
        valuesSb.append("'").append(createdAt.format(DateTimeFormatter.ofPattern(DateUtils.YYYY_MM_DD_HH_MM_SS + ".SSS"))).append("'").append(",");
        fieldSb.append(IotConstant.FIELD_NAME_GATEWAY_DEVICE_ID);
        valuesSb.append("'").append(gatewayDeviceId).append("'");

        field = String.format(field, fieldSb.toString());
        values = String.format(values, valuesSb.toString());

        log.debug("sql:  " + insert + field + values);
        return insert + field + values;
    }

    @Override
    public String build(Map<String, Object> params, String gatewayDeviceId, LocalDateTime createdAt, Map<String, String> pointIdToFieldNameMap) {

        String historyTableName = IotConstant.HISTORY_TABLE_NAME_PRE + gatewayDeviceId;

        String insert = String.format("insert into %s",historyTableName);
        String field = " (%s) ";
        String values = " values(%s) ";

        StringBuilder fieldSb = new StringBuilder();
        StringBuilder valuesSb = new StringBuilder();

        Iterator<Map.Entry<String, Object>> iterator = params.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, Object> entry = iterator.next();
            String fieldName = pointIdToFieldNameMap.get(entry.getKey());
            if (StringUtils.isEmpty(fieldName)) {
                continue;
            }
            fieldSb.append(fieldName).append(",");
            valuesSb.append("'").append(entry.getValue()).append("'").append(",");
        }

        fieldSb.append(IotConstant.FIELD_NAME_CREATED_AT).append(",");
        valuesSb.append("'").append(createdAt.format(DateTimeFormatter.ofPattern(DateUtils.YYYY_MM_DD_HH_MM_SS + ".SSS"))).append("'").append(",");
        fieldSb.append(IotConstant.FIELD_NAME_GATEWAY_DEVICE_ID);
        valuesSb.append("'").append(gatewayDeviceId).append("'");

        field = String.format(field, fieldSb.toString());
        values = String.format(values, valuesSb.toString());

        log.debug("sql:  " + insert + field + values);
        return insert + field + values;
    }
}
